#ifndef _XBASE_PROTOCOL_H_
#define _XBASE_PROTOCOL_H_

#include <stdint.h>
#include <string>
#include "constants.h"
#include "XStringStream.h"

class XBaseProtocol
{
public:
	static const uint16_t _magic_num = XBASE_PROTOCOL_MAGIC;
	static const uint8_t _protocol_ver = XBASE_PROTOCOL_VERSION;
	static const uint32_t _head_length = 13;
	static const uint32_t _offset = 9;
	
public:
	static uint32_t get_head_length()
	{
		return _head_length; // (2 + 1 + 2 + 4 + 4);
	}
	static uint32_t get_body_length(const char* buffer, size_t buffer_size)
	{
		XStringStream decoder(buffer+_offset, buffer_size-_offset, XStringStream::NODELETE, XStringStream::BIGENDIAN);
		uint32_t body_length;
		decoder >> body_length;
		return body_length;
	}
	static void set_body_length(char* buffer, uint32_t body_length)
	{
		XStringStream encoder(buffer+_offset, sizeof(body_length), XStringStream::NODELETE, XStringStream::BIGENDIAN);
		encoder << body_length;
	};
};

class XBaseProtocolHead
{
protected:
	uint16_t   _magic_num;
	uint8_t     _protocol_ver;
	uint16_t   _cmd_type;
	uint32_t   _seq_no;

public:
	uint16_t& magic_num() { return _magic_num; }
	uint8_t& protocol_version() { return _protocol_ver; }
	uint16_t& cmd_type() { return _cmd_type; }
	uint32_t& sequence_num() { return _seq_no; }

	std::string to_string();

	XBaseProtocolHead();
	
	friend XStringStream& operator >> (XStringStream& in, XBaseProtocolHead& other);
	friend XStringStream& operator << (XStringStream& out, XBaseProtocolHead& other);
};

#endif

